fn main() {
    // 闭包不需要显式标注类型，会进行类型推断
    let add_closure = |a, b| {
        a + b
    };
    println!("add: {}", add_closure(1, 2));

    let c1 = |a| {
        a
    };
    // 闭包第一次被调用时，推断出参数类型为i32, 后面传入其他类型参数会报错
    c1(1);
    // c1(String::from("a"));  // panic

    // 也可主动标注类型
    let c2 = |a: i32| -> i32 {a + 1};

    // 闭包能捕获当前作用域内的变量
    let x = 1;
    let c3 = || x + 1;
    println!("x: {}", c3());   
}

//////
struct Cacher<T, V>
where 
    T: Fn(V) -> V,
    V: Copy
{
    cal: T, // 泛型是一个闭包类型
    value: Option<V>,
}

impl<T, V> Cacher<T, V> 
where 
    T: Fn(V) -> V,
    V: Copy
{
    fn new(cal: T) -> Cacher<T, V> {
        Cacher {
            cal,
            value: None,
        }
    }

    fn value(&mut self, arg: V) -> V {
        match self.value {
            Some(v) => v,
            None => {
                // 执行闭包的逻辑，惰性求值
                let v = (self.cal)(arg);
                self.value = Some(v);
                v
            },
        }
    }
}

#[test]
fn call_with_different_values() {
    let mut c = Cacher::new(|a| a);

    let v1 = c.value(1);
    let v2 = c.value(2);

    assert_eq!(v1, v2);
    assert_eq!(v2, 1);
}

